/*************************************************************
 * @file              call_mgr.c
 * @brief
 *
 *
 * @version   Version
 * @author    SealedGhost
 * @data
 *************************************************************/

	#include "call_mgr.h"
	#include "simple_memory.h"
	#include "ccl.h"
	#include <string.h>



	#include "contact.h"

	/** @addtogroup       通话管理
 *
 *   @{
 */


///** 通话事务列表节点类型 */
//typedef struct _CallTransItem CallTransItem;
// struct _CallTransItem{
//	  CallTransaction transaction; /** 通话事务 */
//		 struct _CallTransItem*  pNext;       /** 下一节点指针 */
// };
//
//


//	static CallTransItem CallTransactionList[CALL_TRANSACTION_MAX_NUMBER]  = {0};
//	static uint8_t CallTransactionNumber  = 0;
//
//
//
//	void CallMgr_AddTransaction(CallTransaction* pTransaction)
//	{
//
//	}

	static CallTransaction CallTransactionVector[CALL_TRANSACTION_MAX_NUMBER]  = {0};
	static uint8_t CallTransactionNumber  = 0;


	/**@brief  生成通话记录
  *
  * @param transaction 生成记录所依赖的通话事务
  * @return void
  * @note
  */
	static void CallMgr_GenerateCallLog(CallTransaction* transaction)
	{
		 CallLogItem logItem;
		
Debug("Generate call log:%u,%u", transaction->id, transaction->val);		
		 logItem.who.phoneNumber  = transaction->id;
		 logItem.who.shipNumber   = transaction->val;
		 logItem.dir  = transaction->type;
		 logItem.isMiss  = transaction->state != CALL_CONNECT ? 1 : 0 ;        
         memcpy(&(logItem.when), &(transaction->time), sizeof(transaction->time));
		 CallLog_Add(&logItem);
	}



	/**@brief 向通话事务向量中添加事务
  *
  *
  * @return void
  * @note
  */
	bool static CallMgr_AddTransaction(CallTransaction* pTransaction)
	{
		 if(CallTransactionNumber < CALL_TRANSACTION_MAX_NUMBER){
			 	memcpy(&CallTransactionVector[CallTransactionNumber++], pTransaction, sizeof(CallTransaction));
				return true;
			}
			else{
				  return false;
			}
	}


	/**@brief    添加通话事务
  *
  *
  * @return void
  * @note
  */
	bool CallMgr_AddCallTransaction(CallTransaction* pTransaction)
	{
		 int i  = 0;
		 for(; i < CallTransactionNumber; i++){
				 if(CallTransactionVector[i].id  == pTransaction->id){
						  CallTransactionVector[i].state  = pTransaction->state;
						  return true;
					}
			}

			return CallMgr_AddTransaction(pTransaction);
	}



	/**@brief  更新事务的通话状态
  *
  *
  * @return void
  * @note
  */
	void CallMgr_UpdateTransactionState(uint32_t id, uint8_t newState)
	{
		 int i  = 0;

		 for(; i < CallTransactionNumber; i++){
				 if(CallTransactionVector[i].id == id){
						 CallTransactionVector[i].state  = newState;
						 return ;
					}
			}
	}



	/**@brief     得到指定位置的事务
  *
	* @param     pos  通话事务向量中的位置（1 为基准）
  * @return   所得的通话事务
  * @note
  */
	CallTransaction* CallMgr_GetCallTransaction(int pos)
	{
		 if(pos <= CallTransactionNumber){
				 return &CallTransactionVector[pos-1];
			}
			else{
				 return 0;
			}
	}



	/**@brief  得到指定id的事务
  *
  * @param phoneId 指定的id，也是呼号
  * @return 所得的通话事务
  * @note
  */
	CallTransaction* CallMgr_GetCallTransactionById(uint32_t phoneId)
	{
				int i  = 0;

				for(; i < CallTransactionNumber; i++){
						if(CallTransactionVector[i].id == phoneId){
							return &CallTransactionVector[i];
						}
				}

				return 0;
	}



	/**@brief   删除指定的通话事务
  *
  *
  * @return void
  * @note
  */
	void CallMgr_DeleteCallTransaction(uint32_t id)
	{
//		if( CallTransactionNumber > 0){
//		   if( pos < CallTransactionNumber ){
////						 for(; i < CallTransactionNumber - 1; i++){
////								 memcpy( &(CallTransactionVector[i]),  &(CallTransactionVector[i+1]), sizeof(CallTransaction));
////							}
//						 memcpy( &CallTransactionVector[pos-1], &CallTransactionVector[pos], sizeof(CallTransaction)* (CallTransactionNumber-pos) );
//
//					}
////					else{
////						 memset( &(CallTransactionVector[i]), 0, sizeof(CallTransaction) );
////					}
//
//					CallTransactionNumber--;
//			}
		 int i  = 0;

		 for(; i < CallTransactionNumber; i++){
				 if(CallTransactionVector[i].id == id){
						 memcpy( &(CallTransactionVector[i]),  &(CallTransactionVector[i+1]),  sizeof(CallTransaction)*(CallTransactionNumber -i -1) );
					}

					CallTransactionNumber--;
			}
	}



	/**@brief    得到当前通话事务的数量
  *
  *
  * @return   通话事务数量
  * @note
  */
inline uint8_t CallMgr_GetCallTransactionNumber()
	{
		 return CallTransactionNumber;
	}




	/**@brief  本机呼叫
  *
  * @param phoneId  呼叫的呼号
  * @return 如果呼叫的号码存在于联系人列表则返回被呼船号。
  * @note
  */

	uint32_t CallMgr_Call(uint32_t phoneId)
	{


		CallTransaction newTransaction  = {0};
		LinkMan* man  = Contact_FindByPhoneId(phoneId);

		if(man){
            newTransaction.val  = man->shipNumber;
        }

		newTransaction.id  = phoneId;
		newTransaction.type  = CALL_DIR_OUT;
		newTransaction.state = CALL_MISS;
        SysTime_Get(&(newTransaction.time));
         

		CallMgr_AddCallTransaction(&newTransaction);



		Debug("Start to Call %u", phoneId);

			/// 通知 CCL 发起呼叫，传入呼叫目标的呼号和本机的船号
		CCL_Call(phoneId, 0);
   /// TODO: PostCCLMsg(CallIn, phoneId, boatNumber);

		return newTransaction.val;
	}




	/**@brief  本机接通
  *
  * @param  phoneId 接通的呼号
  * @return void
  * @note
  */
	void CallMgr_Connect(uint32_t phoneId)
	{
		 /// PostCCLMsg(Connect, phoneId, boatNumber)
		 /// CallLog_Add()
        
        /** 如果除了本次接通的呼号对应的事物外，还存在处于接通状态的事物，则自动将那些事物做挂断处理 */
         int i  = 0;
         for(; i < CallTransactionNumber; i++){
             if(CallTransactionVector[i].id  !=  phoneId  &&  CallTransactionVector[i].state  ==  CALL_CONNECT){                     
                 CallMgr_GenerateCallLog( &CallTransactionVector[i] );
				 CallMgr_DeleteCallTransaction(CallTransactionVector[i].id); 
                 break;
             }
         }
        
		 CallMgr_UpdateTransactionState(phoneId, CALL_CONNECT);
		 Debug("Connect with %u", phoneId);
        
         
		
		CCL_Connect(phoneId);
	}



	/**@brief  本机挂断
  *
  * @param phoneId 挂断的呼号
  * @return void
  * @note
  */
	void CallMgr_HangUp(uint32_t phoneId)
	{


		 CallTransaction* pTransaction  = CallMgr_GetCallTransactionById(phoneId);
		 if(pTransaction){
Debug("Hang up %u", phoneId);             
				 CallMgr_GenerateCallLog(pTransaction);
				
				 CallMgr_DeleteCallTransaction(phoneId);
		 }
         else{
Debug("Hang up but not match transaction\n");             
         }
		 

			/// 通知 CCL 挂
			CCL_HangUp(phoneId);
    //PostCCLMsg(HungUp, phoneId, boatNumber)
	}







 /**@brief 来电响应
  *
  *
  * @return void
  * @note
  */
LinkMan* OnCallIn(uint32_t phoneId, uint32_t boatNumber )
{
        CallTransaction newTransaction;


     LinkMan* man  = Contact_FindByPhoneId(phoneId);
     uint16_t  CurrCallNumber  = 0;

Debug("OnCallIn -- phone id:%u, boat number:%u", phoneId, boatNumber);


        newTransaction.id  = phoneId;
        newTransaction.type = CALL_DIR_IN;
        newTransaction.state = CALL_MISS;    
        SysTime_Get( &(newTransaction.time));

     /// 如果来电的是联系人，来电者船号用联系人中记录的船号
     if(man != 0){
                newTransaction.val  = man->shipNumber;
        }
        else{
             newTransaction.val  = boatNumber;
        }

if(! CallMgr_AddCallTransaction(&newTransaction)){
Debug("Add call transaction failed when call in");
        }


return man;

        /// 响提示音 "叮"
}



 /**@brief  对方响铃响应
  *
  *
  * @return void
  * @note   如果拨打时没有从联系人列中中匹配到船号，则在此时得到被呼者的船号
  */
LinkMan* OnRing(uint32_t phoneId, uint32_t boatNumber)
{

     CallTransaction* pTransaction  = CallMgr_GetCallTransactionById(phoneId);
     LinkMan* man  = Contact_FindByPhoneId(phoneId);
//
     if(man != 0){
             boatNumber  = man->shipNumber;
        }

Debug("OnRing -- phone id:%u, boat number:%u", phoneId, boatNumber);

     if(pTransaction){
             if(pTransaction->val == 0){
                     pTransaction->val  = boatNumber;
                }
        }
        else{
Debug("Error!!!!!! OnRing but match none transaction");
            return 0;
        }

        return man;
        /// 响忙音
}



	/**@brief 对方接通响应
  *
  *
  * @return void
  * @note
  */
bool OnConnect(uint32_t phoneId, uint32_t boatNumber)
{
Debug("OnConnect");
    CallMgr_UpdateTransactionState(phoneId, CALL_CONNECT);
    
    return true;
/// 响接通提示音
}



	/**@brief  对方挂断响应
  *
  *
  * @return void
  * @note
  */
bool OnHangUp(uint32_t phoneId, uint32_t boatNumber)
{

    CallTransaction* pTransaction;

Debug("OnHangUp, id = %u", phoneId);		
    
    pTransaction  = CallMgr_GetCallTransactionById(phoneId);
    
    if(pTransaction){				
        CallMgr_GenerateCallLog(pTransaction);
    }
    else{
Debug("Error!!!!!!!!, Hang up but not match any call transaction");     
            return false;
    }

    CallMgr_DeleteCallTransaction(phoneId);
    
    return true;
}



	/**@brief  对方应答忙响应
  *
  *
  * @return void
  * @note
  */
bool OnTellBusy(uint32_t phoneId, uint32_t boatNumber)
{
    CallTransaction* pTransaction;
Debug("OnTellBusy:%u", phoneId);
    pTransaction  = CallMgr_GetCallTransactionById(phoneId);
    
    if(pTransaction){
        CallMgr_GenerateCallLog(pTransaction);
    }
    else{
Debug("Error!!!!!!!!, Tell busy but not match any call transaction");     
            return false;
    }
    CallMgr_DeleteCallTransaction(phoneId);
    
    return true;


/// 响对方忙提示音
}
	
	
	
	
	/**@brief   呼叫失败响应
  * 
  *
  * @return void
  * @note
  */
bool OnCallFail(uint32_t phoneId, uint32_t boatNumber)
{
    CallTransaction* pTransaction;
    
Debug("OnCallFail");
    
    pTransaction  = CallMgr_GetCallTransactionById(phoneId);
    if(pTransaction){
        CallMgr_GenerateCallLog(pTransaction);
    }
    else{
Debug("Error!!!!!!!!, Tell fail but not match any call transaction"); 
        return false;
    }
    CallMgr_DeleteCallTransaction(phoneId);
    
    return true;
}
	
	
	




#ifdef DEBUG
void CallMgr_DumpTransaction()
{
    int  i  = 0;

    Debug("Call transaction:");
    for(; i < CallTransactionNumber; i++){
        Debug("Call %s, phone id:%u, boat number %u, %s", CallTransactionVector[i].type == CALL_DIR_IN ? "in" : "out",
				                                          CallTransactionVector[i].id, CallTransactionVector[i].val,
				                                          CallTransactionVector[i].state == CALL_CONNECT ? "connect" : "not connect");
    }
}
#endif


/** @} */
